//
//  PHPhotoLibrary+Extensions.swift
//  Media
//
//  Created by han on 2021/6/9.
//

import UIKit
import Photos

extension PHPhotoLibrary {
    static func createFetchOptions(_ contentType: AlbumContentType) -> PHFetchOptions {
        let options = PHFetchOptions()
        switch contentType {
        case .image:
            options.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.image.rawValue)
        case .audio:
            options.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.audio.rawValue)
        case .video:
            options.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.video.rawValue)
        default:
            break
        }
        return options
    }
    
    // MARK: fetch
    
    static func fetchAllAlbums(_ contentType: AlbumContentType, _ showEmptyAlbum: Bool = false, _ showSmartAlbum: Bool = true) -> [PHAssetCollection] {
        
        var results = [PHAssetCollection]()
        /// 从result中获取相册
        func fetchCollection(_ fetchResult: PHFetchResult<PHCollection>) {
            for i in 0 ..< fetchResult.count {
                guard let assetCollection = fetchResult[i] as? PHAssetCollection else { continue }
                
                let fetchOptions = PHPhotoLibrary.createFetchOptions(contentType)
                fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
                let assetResult = PHAsset.fetchAssets(in: assetCollection, options: fetchOptions)
                // 空相簿不显示/强制显示
                if assetResult.count > 0 || showEmptyAlbum {
                    // 若相册不为空，或者允许显示空相册，则保存相册到结果数组
                    // 判断如果是“相机胶卷”，则放到结果列表的第一位
                    if assetCollection.assetCollectionSubtype == .smartAlbumUserLibrary {
                        results.insert(assetCollection, at: 0)
                    } else {
                        results.append(assetCollection)
                    }
                }
            }
        }
        
        let option = PHFetchOptions()
        
        // 系统相册
        var fetchCollections : PHFetchResult<PHCollection>
        if showSmartAlbum { // 允许显示系统的“智能相册”
            fetchCollections = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .any, options: option) as! PHFetchResult<PHCollection>
        } else {  // 不允许显示系统的智能相册，但由于在 PhotoKit 中，“相机胶卷”也属于“智能相册”，因此这里从“智能相册”中单独获取到“相机胶卷”
            fetchCollections = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .smartAlbumUserLibrary, options: option) as! PHFetchResult<PHCollection>
        }
        // 遍历系统相册列表
        fetchCollection(fetchCollections)
        
        // 用户自己建立的相册
        let topLevelUserCollections = PHCollectionList.fetchTopLevelUserCollections(with: option)
        // 循环遍历用户自己建立的相册
        // 用户创建的有可能是相簿有可能是文件夹 PHCollection：PHAssetCollection 和 PHCollectionList
        fetchCollection(topLevelUserCollections)
        
        // macOS同步过来的相册
        let macCollections = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .albumSyncedAlbum, options: option) as! PHFetchResult<PHCollection>
        fetchCollection(macCollections)
        
        return results
    }
    
    static func fetchLatestAsset(_ assetCollection: PHAssetCollection) -> PHAsset? {
        let fetchOptions = PHFetchOptions()
        fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
        let assets = PHAsset.fetchAssets(in: assetCollection, options: fetchOptions)
        return assets.lastObject
    }
    
    // MARK: 保存
    
    /// 保存image到特定相册
    func addImageToAlbum(image: UIImage? = nil, imagePathURL: URL? = nil, albumAssetCollection: PHAssetCollection, completionHandler: ((Bool, Error?, Date) -> Void)? = nil) {
        let date = Date()
        self.performChanges {
            // 保存操作
            var assetChangeRequest : PHAssetChangeRequest
            if let image = image {
                assetChangeRequest = PHAssetChangeRequest.creationRequestForAsset(from: image)
            } else if let imagePathURL = imagePathURL {
                assetChangeRequest = PHAssetChangeRequest.creationRequestForAssetFromImage(atFileURL: imagePathURL)!
            } else { return }
            
            assetChangeRequest.creationDate = date
            
            // 添加到相册操作
            guard albumAssetCollection.assetCollectionType == .album else { return }
            // 如果传入的相册类型为标准的相册（非“智能相册”和“时刻”），则把刚刚创建的 Asset 添加到传入的相册中。
            // 创建一个改变 PHAssetCollection 的请求，并指定相册对应的 PHAssetCollection
            let collectionChangeRequest = PHAssetCollectionChangeRequest(for: albumAssetCollection)
            collectionChangeRequest?.addAssets([assetChangeRequest.placeholderForCreatedAsset] as NSFastEnumeration)
            
        } completionHandler: { success, error in
            if !success { print("保存失败")}
            DispatchQueue.main.async {
                completionHandler?(success, error, date)
            }
        }
    }
    
    func addImageToAlbum(cgImage: CGImage, orientation: UIImage.Orientation, albumAssetCollection: PHAssetCollection, completionHandler: ((Bool, Error?, Date) -> Void)? = nil) {
        let image = UIImage(cgImage: cgImage, scale: UIScreen.main.scale, orientation: orientation)
        PHPhotoLibrary.shared().addImageToAlbum(image: image, imagePathURL: nil, albumAssetCollection: albumAssetCollection, completionHandler: completionHandler)
    }
    
    /// 保存video
    func addVideoToAlbum(videoPathURL: URL, albumAssetCollection: PHAssetCollection, completionHandler: ((Bool, Error?, Date) -> Void)? = nil) {
        let date = Date()
        self.performChanges {
            let assetChangeRequest  = PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: videoPathURL)!
            assetChangeRequest.creationDate = date
            guard albumAssetCollection.assetCollectionType == .album else { return }
            let collectionChangeRequest = PHAssetCollectionChangeRequest(for: albumAssetCollection)
            collectionChangeRequest?.addAssets([assetChangeRequest.placeholderForCreatedAsset] as NSFastEnumeration)
            
        } completionHandler: { success, error in
            if !success { print("保存失败")}
            DispatchQueue.main.async {
                completionHandler?(success, error, date)
            }
        }
    }
}
